/*
 * Copyright 2012-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot;

import java.time.Duration;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;

/**
 * {@link SpringApplication} 的 {@code run} 方法监听器。
 * {@link SpringApplicationRunListener} 是通过 {@link SpringFactoriesLoader} 加载的，
 * 并且应该声明一个接受 {@link SpringApplication} 实例和 {@code String[]} 参数的公共构造方法。
 * 每次运行时都会创建一个新的 {@link SpringApplicationRunListener} 实例。
 *
 * @author Phillip Webb
 * @author Dave Syer
 * @author Andy Wilkinson
 * @author Chris Bono
 * @since 1.0.0
 */
public interface SpringApplicationRunListener {

	/**
	 * 在 run 方法刚开始执行时立即调用。可用于非常早期的初始化。
	 * @param bootstrapContext 引导上下文
	 */
	default void starting(ConfigurableBootstrapContext bootstrapContext) {
	}

	/**
	 * 一旦环境准备好但在 {@link ApplicationContext} 创建之前调用。
	 * @param bootstrapContext 引导上下文
	 * @param environment 环境
	 */
	default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
			ConfigurableEnvironment environment) {
	}

	/**
	 * 在 {@link ApplicationContext} 被创建和准备好后调用，但在加载资源之前。
	 * @param context 应用上下文
	 */
	default void contextPrepared(ConfigurableApplicationContext context) {
	}

	/**
	 * 在应用上下文加载完成但尚未刷新之前调用。
	 * @param context 应用上下文
	 */
	default void contextLoaded(ConfigurableApplicationContext context) {
	}

	/**
	 * 应用上下文已刷新，应用程序已启动，但
	 * {@link CommandLineRunner CommandLineRunners} 和 {@link ApplicationRunner
	 * ApplicationRunners} 尚未被调用。
	 * @param context 应用上下文
	 * @param timeTaken 启动应用程序所花费的时间，若未知则为 {@code null}
	 * @since 2.6.0
	 */
	default void started(ConfigurableApplicationContext context, Duration timeTaken) {
		started(context);
	}

	/**
	 * 应用上下文已刷新，应用已启动，但
	 * {@link CommandLineRunner CommandLineRunners} 和 {@link ApplicationRunner
	 * ApplicationRunners} 尚未被调用。
	 * @param context 应用上下文
	 * @since 2.0.0
	 * @deprecated 自 2.6.0 起弃用，计划在 3.0.0 中移除，推荐使用
	 * {@link #started(ConfigurableApplicationContext, Duration)}
	 */
	@Deprecated
	default void started(ConfigurableApplicationContext context) {
	}

	/**
	 * 在 run 方法即将结束前调用，此时应用上下文已刷新，且所有
	 * {@link CommandLineRunner CommandLineRunners} 和
	 * {@link ApplicationRunner ApplicationRunners} 都已被调用。
	 * @param context 应用上下文
	 * @param timeTaken 应用准备就绪所花费的时间，若未知则为 {@code null}
	 * @since 2.6.0
	 */
	default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
		running(context);
	}

	/**
	 * 在 run 方法即将结束前调用，此时应用上下文已刷新，且所有
	 * {@link CommandLineRunner CommandLineRunners} 和
	 * {@link ApplicationRunner ApplicationRunners} 都已被调用。
	 * @param context 应用上下文
	 * @since 2.0.0
	 * @deprecated 自 2.6.0 起弃用，计划在 3.0.0 中移除，推荐使用
	 * {@link #ready(ConfigurableApplicationContext, Duration)}
	 */
	@Deprecated
	default void running(ConfigurableApplicationContext context) {
	}

	/**
	 * 应用运行过程中发生异常时调用。
	 * @param context 应用上下文，若在上下文创建之前就发生了异常，则为 {@code null}
	 * @param exception 异常信息
	 * @since 2.0.0
	 */
	default void failed(ConfigurableApplicationContext context, Throwable exception) {
	}

}
